/*
============================================================================
Name        : util.c
Author      : Jian (raphyer@hotmail.com)
Version     :
Copyright   : GPL
Description : util.c - source file
============================================================================
*/

/* INCLUDE FILES */
#include "dd_util.h"
#include "dd_log.h"
#include "sd_platform.h"

static sd_rlock* _lockFilelock = NULL ;
static sd_file*           _lockFile = NULL ;

int dd_util_init() 
{
    char name[DD_MAX_FILE_NAME_LEN + 1] = {0} ;
    
    sd_get_log_path(name) ;
    __DD_ASSERT_DEFENSE(name[0] != 0, return -1) ;
    
    strcat(name, "lock.log") ;

    _lockFilelock = sd_create_rlock() ;
    __DD_ASSERT_DEFENSE(_lockFilelock, return -1) ;

    _lockFile = sd_file_open((const DD_UTF8*)name, DD_FILE_REPLACE) ;
    __DD_ASSERT_DEFENSE(_lockFile, return -1) ;

    return 0 ;
}

void dd_log_sem(void* lock, const char* fileName, int line, int isWait) 
{
    char buf[DD_MAX_FILE_NAME_LEN + 100 + 1] = {0} ;

    if (!_lockFilelock || !_lockFile)
        return ;

    sd_wait_rlock(_lockFilelock) ;
    
    sprintf(buf, "%s %u lock in %s %d\r\n", isWait ? "wait" : "post", lock, fileName, line) ;

    sd_file_write(_lockFile, buf, strlen(buf)) ;

    sd_file_fulsh(_lockFile) ;

    sd_post_rlock(_lockFilelock) ;
}

int dd_atoi(const char* str, int* value) 
{
    int i = 0 ;
    int len = 0 ;
    int maxIntLen = 10 ;

    __DD_ASSERT_DEFENSE(str && value, return -1) ;
    
    len = strlen(str) ;

    if (len > maxIntLen)
        return -1;

    for (; i < len; i++) {
        if (str[i] < '0' || str[i] > '9')
            return -1 ;
    }
    
    *value = atoi(str) ;

    return 0 ;
}

char* dd_newstr(const char* str) 
{
    __DD_ASSERT_DEFENSE(str, return NULL) ;

    return dd_newstr_with_len(str, strlen(str)) ;
}

char* dd_newstr_with_len(const char* str, int len) 
{
    char* ret = NULL ;

    __DD_ASSERT_DEFENSE(str, return NULL) ;

    ret = (char*)dd_malloc(len + 1) ;
    __DD_CHECK_MEM(ret, len + 1, return NULL) ;

    memcpy(ret, str, len) ;
    return ret ;
}

char* dd_str_tolower(const char* str) 
{
    char* ret = dd_newstr(str) ;
    int   i = 0 ;
    int   len = 0 ;  

    __DD_ASSERT_DEFENSE(ret, return NULL) ;
    
    len = strlen(ret) ;
    
    for (; i < len; i++) {
        if (ret[i] >= 'A' && ret[i] <= 'Z')
            ret[i] += 32 ;
    }
    
    return ret ;
}

char* dd_str_trim(char* str) 
{
    char* start = NULL ;
    char* end   = NULL ; 
    int   len   = 0 ;

    __DD_ASSERT_DEFENSE(str, return NULL) ;
    
    start = str ;
    end = str + strlen(str) - 1;
    
    while(start <= end) {
        if (*start != 0x20) 
            break ;
        start++ ;
    }

    while(end >= str) {
        if (*end != 0x20)
            break ;
        end-- ;
    }

    if (end >= start) {
        memmove(str, start, end - start + 1) ;
        str[end - start + 1] = 0 ;
    } else {
        str[0] = 0 ;
    }

    return str ;
}


char* dd_str_split(const char* str, const char* beginSep, const char* endSep) 
{
    const char* begin = NULL ;
    const char* end = NULL ;

    __DD_ASSERT_DEFENSE(str && beginSep && endSep, return NULL) ;

    begin = strstr(str, beginSep) ;
    if (!begin)  return NULL ;

    begin += strlen(beginSep) ;
    
    end = strstr(str, endSep) ;
    if (!end)  return NULL ;

    return dd_newstr_with_len(begin, end - begin) ;
}

__dd_inline static char _convert_hex(char hexChar) 
{
    if (hexChar >= '0' && hexChar <= '9')
        return hexChar - '0' ;
    
    if (hexChar >= 'a' && hexChar <= 'f')
        return  hexChar - 'a' + 10 ;

    if (hexChar >= 'A' && hexChar <= 'F')
        return  hexChar - 'A' + 10 ;

    return -1 ;
}

int dd_str_hex2i(const char* hexStr) 
{
    int  ret = 0 ;
    char tmpChar = -1 ;

    __DD_ASSERT_DEFENSE(hexStr && _convert_hex(*hexStr) >= 0, return -1) ;
    
    /* like "10f" return 271 */
    while((tmpChar = _convert_hex(*hexStr)) >= 0) {
        ret = (ret << 4) + tmpChar;
        hexStr++ ;
    }
    
    return ret ;
}


#include "zlib.h"
#define segment_size 8000//largest tcp data segment

int dd_ungzip(char* src, int srcLen, char* dest, int destLen)
{
    int ret  = -1;
    z_stream d_stream;

    strcpy((char*)dest, "garbage");

    d_stream.zalloc   = Z_NULL;
    d_stream.zfree    = Z_NULL;
    d_stream.opaque   = Z_NULL;
    d_stream.next_in  = Z_NULL;

    ret = inflateInit2(&d_stream, 47);
    if(ret != Z_OK) {
        dd_log_error("inflateInit2 got error: %d",ret);
        return -1;
    }

    d_stream.next_in   = (DD_BYTE*)src;
    d_stream.avail_in  = srcLen;

    d_stream.next_out  = (DD_BYTE*)dest;
    d_stream.avail_out = destLen;

    ret = inflate(&d_stream, Z_NO_FLUSH);
    
    if (ret == Z_NEED_DICT || ret < Z_OK) {
        dd_log_error("inflate got error: %d",ret);
        ret = -1 ;
        goto _end ;
    }
    
    ret = destLen - d_stream.avail_out ;

    _end:
    inflateEnd(&d_stream);
    return ret;
}


int dd_file_size(sd_file* file, sd_semp* lock) 
{
    int curPos = 0 ;
    int size   = 0 ;

    __DD_ASSERT_DEFENSE(file, return 0) ;

    if (lock) dd_wait_sem(lock, return 0) ;
            
    curPos = sd_file_tell(file) ;
    __DD_ASSERT_DEFENSE(curPos >= 0, goto _error) ;

    if (sd_file_seek(file, 0, DD_SEEK_END) < 0) {
        __DD_ASSERT(0) ;
        goto _error ;
    }

    size = sd_file_tell(file) ;
    __DD_ASSERT_DEFENSE(size >= 0, goto _error) ;

    if (sd_file_seek(file, curPos, DD_SEEK_SET) < 0)
        __DD_ASSERT(0) ;
    
    if (lock)  dd_post_sem(lock, ;) ;
    return size ;

    _error:
    if (lock)  dd_post_sem(lock, ;) ;
    return 0 ;
}

int dd_file_read(sd_file* file, void* ptr, int len, int pos, sd_semp* lock) 
{
    int ret = -1 ;

    __DD_ASSERT_DEFENSE(file && ptr, return ret) ;

    if (lock) dd_wait_sem(lock, return ret) ;

    sd_file_seek(file, pos, DD_SEEK_SET) ;
    ret = sd_file_read(file, ptr, len) ;

    if (lock)  dd_post_sem(lock, ;) ;
    return ret;
}

int dd_file_write(sd_file* file, void* ptr, int len, int pos, sd_semp* lock)
{
    int ret = -1 ;

    __DD_ASSERT_DEFENSE(file && ptr, return ret) ;

    if (lock) dd_wait_sem(lock, return ret) ;

    sd_file_seek(file, pos, DD_SEEK_SET) ;
    ret = sd_file_write(file, ptr, len) ;

    if (lock)  dd_post_sem(lock, ;) ;
    return ret;
}

/* End of File */
